package com.greate.community.controller;

import com.alibaba.fastjson.JSONArray;
import com.greate.community.constant.CommunityConstant;
import com.greate.community.constant.ExpType;
import com.greate.community.entity.*;
import com.greate.community.entity.dto.AddCommentDTO;
import com.greate.community.event.EventProducer;
import com.greate.community.service.CommentService;
import com.greate.community.service.LikeService;
import com.greate.community.service.UserService;
import com.greate.community.util.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 评论/回复
 */
@RestController
@RequestMapping("/comment")
public class CommentController extends BaseController implements CommunityConstant {

    @Autowired
    private UserService userService;

    @Autowired
    private LikeService likeService;

    @Autowired
    private CommentService commentService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private EventProducer eventProducer;

    /**
     * 添加评论
     */
    @PostMapping("/add")
    public Result addComment(@RequestBody @Validated AddCommentDTO addCommentDTO) {
        Comment comment = new Comment();

        comment.setContent(addCommentDTO.getContent());
        List<String> filter = addCommentDTO.getPicUrls().stream().filter(url -> !StringUtils.isBlank(url)).collect(Collectors.toList());
        comment.setPicUrls(StringListConvertor.join(filter));
        comment.setParentId(addCommentDTO.getParentId());
        comment.setRootId(addCommentDTO.getRootId());
        comment.setPostId(addCommentDTO.getPostId());
        comment.setParentUserId(addCommentDTO.getParentUserId());

        comment.setUserId(getUser().getId());
        comment.setLikeCount(0);
        comment.setStatus(0); // 正常
        comment.setCreateTime(new Date());
        commentService.addComment(comment);

        // 触发评论事件（系统通知） - 自己评论自己不通知
        if (comment.getParentUserId() != comment.getUserId()) {
            Event event = new Event()
                    .setTopic(TOPIC_COMMNET)
                    .setUserId(getUser().getId())
                    .setEntityId(comment.getParentId())
                    .setEntityUserId(comment.getParentUserId()) // 发送给谁
                    .setData("postId", comment.getPostId())
                    .setData("commentId", comment.getId());
            if (comment.getParentId() == 0) {
                event.setEntityType(ENTITY_TYPE_POST);
            } else {
                event.setEntityType(ENTITY_TYPE_COMMENT);
            }
            eventProducer.fireEvent(event);
        }

        // 触发增加经验事件
        Event expEvent = new Event()
                .setTopic(TOPIC_EXP)
                .setUserId(getUser().getId())
                .setData("type", ExpType.EXP_COMMENT.getName());
        eventProducer.fireEvent(expEvent);

        // 触发发帖事件，通过消息队列将其存入 Elasticsearch 服务器
        Event event = new Event()
                .setTopic(TOPIC_PUBLISH)
                .setUserId(comment.getUserId())
                .setEntityType(ENTITY_TYPE_POST)
                .setEntityId(comment.getPostId());
        eventProducer.fireEvent(event);

        // 计算帖子分数
        String redisKey = RedisKeyUtil.getPostScoreKey();
        redisTemplate.opsForSet().add(redisKey, comment.getPostId());

        return new Result("success", Result.SUCCESS, "评论成功");
    }

    /**
     * 获取帖子的评论列表
     */
    @GetMapping("/list/{discussPostId}")
    public Result getCommentsByPostId(@PathVariable("discussPostId") int discussPostId,
                                      @RequestParam(value = "replyLimit", defaultValue = "3") int replyLimit,
                                      Page page) {
        page.setPath("/comment/get/" + discussPostId);

        // 帖子下评论总数
        page.setRows(commentService.findCommentCountByPostId(discussPostId));

        // 帖子的评论列表
        List<Comment> commentList = commentService.findCommentByPost(
                discussPostId, page.getOffset(), page.getLimit());

        // 封装评论及其相关信息
        List<Map<String, Object>> commentVoList = new ArrayList<>();
        if (commentList != null && !commentList.isEmpty()) {
            commentList.forEach(comment -> {
                Map<String, Object> commentVo = new HashMap<>();
                shieldContent(comment);
                commentVo.put("comment", StringListConvertor.toJsonObject(comment, "picUrls")); // 评论
                commentVo.put("user", userService.findUserById(comment.getUserId())); // 发布评论的作者
                // 当前登录用户对该评论的点赞状态
                int likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus(
                        getUser().getId(), ENTITY_TYPE_COMMENT, comment.getId());
                commentVo.put("likeStatus", likeStatus);
                // 存储每个评论对应的回复, 查询点赞量最高的前3条回复
                List<Comment> replyList = commentService.findReplyByComment(comment.getId(), 0, replyLimit);
                List<Map<String, Object>> replyVoList = new ArrayList<>(); // 封装对评论的评论和评论的作者信息
                if (replyList != null) {
                    replyList.forEach(reply -> {
                        Map<String, Object> replyVo = new HashMap<>();
                        shieldContent(reply);
                        replyVo.put("reply", StringListConvertor.toJsonObject(reply, "picUrls")); // 回复
                        replyVo.put("user", userService.findUserById(reply.getUserId())); // 发布该回复的作者
                        // 当前登录用户对该回复的点赞状态
                        int replyLikeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus(
                                getUser().getId(), ENTITY_TYPE_COMMENT, reply.getId());
                        replyVo.put("likeStatus", replyLikeStatus); // 当前登录用户的点赞状态

                        replyVoList.add(replyVo);
                    });
                }
                commentVo.put("replys", replyVoList);

                // 每个评论对应的回复数量
                int replyCount = commentService.findReplyCount(comment.getId());
                commentVo.put("replyCount", replyCount);

                commentVoList.add(commentVo);
            });
        }

        JSONArray result = (JSONArray) JSONArray.toJSON(commentVoList);
        page.setResult(result);

        return new Result("success", Result.SUCCESS, page);
    }

    @GetMapping("/reply-list/{rootId}")
    public Result findReplyByCommentId(@PathVariable int rootId, Page page) {
        page.setPath("/reply-list/" + rootId);

        // 跟评论下回复总数
        page.setRows(commentService.findReplyCount(rootId));

        // 帖子的评论列表
        List<Comment> replyList = commentService.findReplyByComment(
                rootId, page.getOffset(), page.getLimit());

        // 封装评论及其相关信息
        List<Map<String, Object>> replyVoList = new ArrayList<>();
        if (replyList != null && !replyList.isEmpty()) {
            replyList.forEach(reply -> {
                Map<String, Object> commentVo = new HashMap<>();
                shieldContent(reply);
                commentVo.put("comment", StringListConvertor.toJsonObject(reply, "picUrls"));
                commentVo.put("user", userService.findUserById(reply.getUserId())); // 发布评论的作者
                // 当前登录用户对该评论的点赞状态
                int likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus(
                        getUser().getId(), ENTITY_TYPE_COMMENT, reply.getId());
                commentVo.put("likeStatus", likeStatus);

                replyVoList.add(commentVo);
            });
        }

        JSONArray result = (JSONArray) JSONArray.toJSON(replyVoList);
        page.setResult(result);

        return new Result("success", Result.SUCCESS, page);
    }

    /**
     * 禁用评论（禁用仍然可以查询出来，不修改帖子分数）
     *
     * @return
     */
    @PostMapping("/disable/{id}")
    public Result setDisable(@PathVariable int id) {
        commentService.updateStatus(id, 1);
        return new Result("success", Result.SUCCESS, "禁用成功");
    }

    /**
     * 删除评论
     *
     * @return
     */
    @PostMapping("/delete/{id}")
    public Result setDelete(@PathVariable int id) {
        Comment comment = commentService.findCommentById(id);
        if (comment == null) {
            return new Result("fail", "1", "评论不存在");
        }
        if (getUser().getId() != comment.getUserId()) {
            return new Result("fail", "2", "只能删除自己的评论");
        }

        commentService.deleteComment(comment);

        // 触发发帖事件，通过消息队列将其存入 Elasticsearch 服务器
        Event event = new Event()
                .setTopic(TOPIC_PUBLISH)
                .setUserId(comment.getUserId())
                .setEntityType(ENTITY_TYPE_POST)
                .setEntityId(comment.getPostId());
        eventProducer.fireEvent(event);

        // 计算帖子分数
        String redisKey = RedisKeyUtil.getPostScoreKey();
        redisTemplate.opsForSet().add(redisKey, comment.getPostId());

        return new Result("success", Result.SUCCESS, "删除成功");
    }

    private void shieldContent(Comment comment) {
        if (comment.getStatus() == 1) {
            comment.setContent("该评论因违反社区规定，已无法查看");
            comment.setPicUrls(null);
        }
    }
}
